#ifndef DATACONTAINER_H
#define DATACONTAINER_H
#include <malloc.h>
#include <memory.h>
#include <stdbool.h>
typedef unsigned char byte;
//定义list为一个表 其中有若干元组 元组无关
#define GenerateListClass(type) \
typedef struct\
{\
    int maxlen;\
    int nowlen;\
    int unitsize;\
    type *data;\
}List_##type;
//通用列表 用于通用函数操作 无类型 类型依据unitsize而定
GenerateListClass(void)
//用于表示纯数据
GenerateListClass(byte)

#define DefineListWithSign(type,sign,name) \
sign List_##type name;

#define DefineList(type,name) List_##type name;
//强制类型转换 注意此处只进行指针转换
//转换到某个类型的列表
#define CastToTyped(lst,type) ({if(lst->unitsize==sizeof(type)) (List_##type *)lst;else {printf("类型转换错误:%s->List_%s",#lst,#type);}})
inline void *F_CastToTypedComputed(void *lst,int unitsize)
{
    List_void *vlst=CastToVoid(lst);
    if((vlst->unitsize*vlst->unitsize)%unitsize!=0)
    {
        printf("长度错误！");
        return NULL;
    }
    vlst->nowlen=(vlst->unitsize*vlst->nowlen)/unitsize;
    vlst->unitsize=unitsize;
    return vlst;
}
//进行兼容的（数据长度兼容的类型转换 自动计算转换后长度)
#define CastToTypedComputed(lst,type) (List_##type *)F_CastToTypedComputed(lst,sizeof(type))
//转换为通用列表
#define CastToVoid(lst) (List_void *)lst
//移动列表 不复制数据 dst将和src表示同一个列表 理论上此操作后src无效
#define MoveList(dst,src) *dst=*src

//通用函数部分 为了避免强制指针类型转换这里全部用void * 通用函数接收的全部是列表的指针而非列表
//初始化一个列表
void G_InitList(void *lst,int unitsize,int maxsize);
//在列表中添加一项
bool G_AddItem(void *lst,void *item);
//在列表中删除一项
bool G_DelItem(void *lst,int idx);
//用纯粹数据比对从列表中查找完全相等的一项并返回index
int G_FindItem(void *lst,void *itemdata);//查找数据
//复制数据从一个列表到另一个列表 要求unitsize相等
bool G_ListCopy(void *dst,void *src);
//释放一个list 这是唯一一个传指针的一般工具函数
//void FreeList(void *lst);
//Free后的list不可使用 需要丢弃 其中所有数据全部为0
#define FreeList(lst) ({free(lst.data);lst.data=NULL;})


//byte列表是字节列表 失去了类型信息 unitsize为1 长度即为数据长度 仅用来做数据的读取保存等
//void列表是通用列表 其中unitsize得以保留 只是类型声明上data指针变成了void型 语义上不应对void列表做直接操作
//void列表可以直接由强制类型转换转换为任何类型的列表
//序列化 列表元数据一并保存


//此函数直接建立一个listbyte data指针等于原data指针 不复制数据
List_byte  GenerateFromData(void *data,int size);
//返回一个lst的序列化副本 其中存储了元数据
List_byte  Serialize(void *lst);
//反序列化为通用列表 元数据自动读取
List_void  DeSerialize(List_byte data);
//反序列化为具体类型列表
#define DeSerializeToType(bytes,type) ({List_void _vlst=DeSerialize(bytes);*(List_##type *)&_vlst;})
//写入文件
void WriteBytesToFile(List_byte bytes,const char *filename);
List_byte ReadBytesFromFile(const char *filename);
//以下列表都为“列表指针”
#define InitList(type,lst,maxsize) G_InitList(&lst,sizeof(type),maxsize)

#define NewList(type,name) name=(List_##type *)malloc(sizeof(List_##type));memset(name,0,sizeof(name))

//操作函数 用户直接使用 所有name都为一个列表名 为列表本身不是指针

#define AddItem(name,item) G_AddItem(&name,&item)

#define DelItem(name,idx) G_DelItem(&name,idx)

#define InsertItem(name,idx) G_DelItem(&name,idx)

#define FindItem(name,item) G_FindItem(&name,&item)

//返回item的指针
#define GetItemPointer(name,idx) ({if(idx>=name.nowlen) {printf("错误，列表索引超界");}name.data+idx;})
//需要GCC的块语句扩展才能编译 直接由索引得到idx的值
#define GetItem(name,idx) (*GetItemPointer(name,idx))


//此二者 Find返回第一个找到的item的位置 where返回一个result list
//Find 返回的是item的位置 0开始
//Get返回一个item的复制
#define Get(name,type,judge) ({\
                               List_##type *lst=(List_##type *)&name;\
                               type ret;\
                               for(int i=0;i<lst->nowlen;++i){\
                               const type *value=lst->data+i;\
                                if(judge){\
                                ret=*(type *)value;\
                                    break;}\
                               }\
                               ret;\
                               })

//Find现在返回index即 item的位置 可通过 GetItem或GetItemPointer来获取对应item或其指针（要修改的话)
#define Find(name,type,judge) ({\
                               List_##type *lst=(List_##type *)&name;\
                               int ret=-1;\
                               for(int i=0;i<lst->nowlen;++i){\
                                const type *value=lst->data+i;\
                                if(judge){\
                                ret=i;\
                                    break;}\
                               }\
                               ret;\
                               })

//初始100容量 会随着additem变大
#define Where(name,type,judge) ({\
                               List_##type *lst=(List_##type *)&name;\
                               DefineList(type,retlist);\
                               InitList(type,retlist,100); \
                               for(int i=0;i<lst->nowlen;++i){\
                               const type *value=lst->data+i;\
                                if(judge){\
                                  AddItem(retlist,*(type *)value);\
                                    }\
                               }\
                               retlist;\
                               })

//附加函数部分
//辅助函数 forEach 用于遍历列表 i为一个idx的名字 __i为固定名字
#define forEach(lst) ({\
List_void *__lst=(List_void *)&lst;
#define IndexAs(i) \
for(int __i=0;__i<__lst->nowlen;++__i){\
    int i=__i;

#define ValueAs(type,value) \
type value=GetItem((*(List_##type *)__lst),__i);\
(


#define End );\
}\
});

#define ValuePtrAs(type,value)\
    type *value=GetItemPointer((*(List_##type *)__lst),__i);\
    (

//针对字符串 ，由于char *无法序列化反序列化 且表中不能有指针数据因此这里添加varchar类型
#define varchar(n,name) char name[n+1]
//标准字符串长度 512 一般情况下足够
#define string(name) varchar(512,name)
#define longstring(name) varchar(2048,name)
//定义varchar操作的便捷函数
#define copy(dest,src) ({if(sizeof(dest)-1>=strlen(src)) strcpy(dest,src);else printf("复制字符串错误！目标varchar变量长度不够");})
#define equal(dest,src) (strcmp(dest,src)==0)
#define not_equal(dest,src) (!equal(dest,src))
typedef enum
{
    Admin=0,
    Normal=1
}UserType;

//kv对 用于指定附加信息
typedef struct UserInfoItem
{
    //指定哪个用户的附加信息
    varchar(16,username);
    //附加信息的名字
    varchar(32,key);
    //附加信息项的描述
    varchar(64,desc);
    //附加信息的值
    string(value);
}UserInfoItem;
GenerateListClass(UserInfoItem)
DefineListWithSign(UserInfoItem,extern,UserInfoList)
typedef struct User
{
    //用户名
    varchar(16,name);
    //密码
    varchar(16,password);
    UserType type;
}User;
GenerateListClass(User)
DefineListWithSign(User,extern,UserList) //定义用户列表 extern用于保证唯一性
typedef struct
{
    long long tks;
    int year;
    int month;
    int day;
    //时间
    int hour;
    int min;
    int sec;
}DateTime;

//活动部分

typedef struct
{
    int id; //活动号
    varchar(32,name);//活动名
    varchar(16,e_username); //发起者用户名
    DateTime etime;//发起时间
    DateTime starttime;//开始时间
    DateTime endtime;//结束时间
    string(description); //活动描述

}Activity;
GenerateListClass(Activity)
DefineListWithSign(Activity,extern,Activites)

//留言列表  留言为n->n关系 此为全码关系
typedef struct
{
    varchar(16,from_username);
    varchar(16,to_username);
    string(message);
}Message;
GenerateListClass(Message)
DefineListWithSign(Message,extern,MessageList)


#endif // DATACONTAINER_H
